﻿
using System;
using System.Collections.Generic;
using Cinemachine;
using UnityEngine;
using Yoozoo.Core.Extensions.Engine;
using Yoozoo.Framework.Core;
using Yoozoo.Gta.Common;

namespace Gameplay.PVE.Survivor
{
    public class MissionManager: BattleSingleton<MissionManager>
    {
        private class MissionTask
        {
            public int index;
            public EBattleTaskType taskType;
            public int TaskStageType;// 0阶段成功任务，1阶段不能失败任务
            public int counter = 0;
            public List<float> param;
            public bool hasFinish = false;
            public float startTime;
            public BattleGameObject sign;
            public string signPath;
            public RpgMissionTaskConfig config;
            public bool showUIEvent;
            
            private MapInteractableData interactable;
            private BattleMapRegion interactableRegion;
            private List<int> interactableState = new List<int>();
            private List<float> interactableParams = new List<float>();

            private BattleUnit targetUnit;

            private bool bossEventBinded;
            private BattleUnit bossUnit;
            private Vector3 compassPosition = BattleConstValue.DEFAULT_POINT;
            
            public void Init()
            {
                bossEventBinded = false;
                if (taskType == EBattleTaskType.HoldOnByTime)
                {
                    startTime = TimeManager.time;
                }
                else if (taskType == EBattleTaskType.InteractiveRegion || taskType == EBattleTaskType.TeamReachRegion)
                {
                    if (taskType == EBattleTaskType.InteractiveRegion)
                    {
                        interactable = StageManager.Instance.GetInteractable((int)GetParam(0));
                        interactableRegion = StageManager.Instance.GetRegion(interactable.regionId);
                        interactableState.Clear();
                        interactableParams.Clear();
                        for (int i = 0; i < interactable.events.Count; i++)
                        {
                            interactableState.Add(0);
                            interactableParams.Add(0);
                        }
                    }
                    else
                    {
                        interactableRegion = StageManager.Instance.GetRegion((int)GetParam(0));
                    }

                    startTime = -1;
                    //显示指南针
                    if (config.show_compass == 1)
                    {
                        StageManager.Instance.TeamGroup.AddGuideCompass(interactableRegion.position);
                    }
                }
                else if (taskType == EBattleTaskType.UnitReachRegion)
                {
                    interactableRegion = StageManager.Instance.GetRegion((int)GetParam(0));
                    targetUnit = UnitManager.Instance.GetUnitByHeroId((int)GetParam(1));
                }
                else if (taskType == EBattleTaskType.UnitRescue)
                {
                    var heroId = (int)GetParam(0);
                    targetUnit = UnitManager.Instance.GetUnitByHeroId(heroId);
                    if (targetUnit != null)
                    {
                        targetUnit.onHpChange = OnUpdateProgress;
                    }
                    else
                    {
                        UnitManager.Instance.AddUnitHpChangeCallback(heroId, OnUpdateProgress);
                    }
                }
                else if (taskType == EBattleTaskType.KillUnit)
                {
                    var type = (int)GetParam(2);
                    if (type == 1)
                    {
                        var heroId = (int)GetParam(0);
                        bossUnit = UnitManager.Instance.GetUnitByHeroId(heroId);
                        if (bossUnit != null)
                        {
                            bossUnit.onHpChange = OnUpdateProgress;
                        }
                        else
                        {
                            UnitManager.Instance.AddUnitHpChangeCallback(heroId, OnUpdateProgress);
                        }
                    }

                    if (config.show_compass == 1)
                    {
                        var heroId = (int)GetParam(0);
                        targetUnit = UnitManager.Instance.GetUnitByHeroId(heroId);
                        if (targetUnit != null)
                        {
                            targetUnit.onPositionChange = UpdateCompass;
                        }
                        else
                        {
                            UnitManager.Instance.AddUnitPositionChangeCallback(heroId, UpdateCompass);
                        }
                    }
                }
                CreateSignEffect();
                OnUpdateProgress();
            }

            private void UpdateCompass()
            {
                if (targetUnit == null)
                {
                    targetUnit = UnitManager.Instance.GetUnitByHeroId((int)GetParam(0));
                }

                if (targetUnit != null)
                {
                    var position = targetUnit.position;
                    if (compassPosition == BattleConstValue.DEFAULT_POINT)
                    {
                        StageManager.Instance.TeamGroup.AddGuideCompass(position);
                    }
                    else
                    {
                        StageManager.Instance.TeamGroup.ChangeGuideCompassPosition(compassPosition,position);
                    }
                    compassPosition = position;
                }
            }

            private Vector3 GetSignPosition()
            {
                if (taskType == EBattleTaskType.InteractiveRegion || taskType == EBattleTaskType.TeamReachRegion)
                {
                    var region = interactableRegion;
                    return region.position;
                }
                return Vector3.zero;
            }

            public float GetParam(int index)
            {
                if (index >= param.Count)
                {
                    return 0;
                }
                return param[index];
            }

            public bool OnGetDollar()
            {
                if (hasFinish)
                {
                    return false;
                }

                if (taskType != EBattleTaskType.GetDollar)  
                {
                    return false;
                }
                var count = GetParam(0);
                var currentCount = SurvivorDataManager.Instance.dollar;
                if (currentCount >= count)
                {
                    hasFinish = true;
                }
                OnUpdateProgress();
                return hasFinish;
            }
            
            public bool OnKill(int team,int heroId)
            {
                if (hasFinish)
                {
                    return false;
                }
                if (taskType == EBattleTaskType.KillUnit)
                {
                    var unitId = GetParam(0);
                    var count = GetParam(1);
                    if (team == 2 && (unitId == heroId || unitId == 0))
                    {
                        counter++;
                        hasFinish = counter >= count;
                        OnUpdateProgress();
                        if (compassPosition != BattleConstValue.DEFAULT_POINT)
                        {
                            StageManager.Instance.TeamGroup.RemoveGuideCompass(compassPosition);
                            compassPosition = BattleConstValue.DEFAULT_POINT;
                        }

                        if (hasFinish && bossUnit != null)
                        {
                            StageManager.Instance.ShowBossDeadCamera(bossUnit);
                        }

                        if (!hasFinish)
                        {
                            targetUnit = UnitManager.Instance.GetUnitByHeroId(heroId);
                            if (config.show_compass == 1)
                            {
                                if (targetUnit != null)
                                {
                                    targetUnit.onPositionChange = UpdateCompass;
                                }
                                else
                                {
                                    UnitManager.Instance.AddUnitPositionChangeCallback(heroId, UpdateCompass);
                                }
                            }
                        }
                        return hasFinish;
                    }
                }
                else if (taskType == EBattleTaskType.UnitRescue)
                {
                    if (this.param.Count >= 1)
                    {
                        var resuceID = GetParam(0);
                        if (resuceID == heroId)
                        {
                            StageManager.Instance.Lose();   
                        }
                    }
                }
                return false;
            }

            public bool OnUnitReachRegion()
            {
                if (hasFinish)
                {
                    return false;
                }

                if (targetUnit == null)
                {
                    targetUnit = UnitManager.Instance.GetUnitByHeroId((int)GetParam(1));
                }

                if (targetUnit == null)
                {
                    return false;
                }
                OnUpdateProgress();
                if (BattleHelper.IsInRegion(targetUnit.Position, interactableRegion))
                {
                    hasFinish = true;
                    return true;
                }
                return false;
            }

            public bool OnCheckRegion()
            {
                if (BattleHelper.IsInRegion(StageManager.Instance.TeamGroup.Position, interactableRegion))
                {
                    RemoveSignEffect();
                    hasFinish = true;
                    StageManager.Instance.TeamGroup.RemoveGuideCompass(interactableRegion.position);
                }
                OnUpdateProgress();
                return hasFinish;
            }

            public bool OnCheckInteractable()
            {
                if (interactable.Finished)
                {
                    RemoveSignEffect();
                    hasFinish = true;
                    StageManager.Instance.TeamGroup.RemoveGuideCompass(interactableRegion.position);
                }
                else
                {
                    if (interactable.IsInteracting())
                    {
                        RemoveSignEffect();
                    }
                    else
                    {
                        CreateSignEffect();
                    }
                }
                OnUpdateProgress();
                return hasFinish;
            }

            public bool OnCheckTimer()
            {
                
                var time = GetParam(0);
                if (TimeManager.time - startTime > time)
                {
                    hasFinish = true;
                }
                OnUpdateProgress();
                return hasFinish;
            }

            private void CreateSignEffect()
            {
                if (sign != null)
                {
                    return;
                }
                if (config.sign_id > 0)
                {
                    sign = BattlePoolManager.Instance.Get(config.sign_id);
                    sign.Position = GetSignPosition();
                    sign.Parent = SurvivorManager.Instance.Root;
                    var scale = config.sign_size;
                    sign.Scale = new Vector3(scale, scale, scale);
                }
            }
            
            private void RemoveSignEffect()
            {
                if (sign != null)
                {
                    BattlePoolManager.Instance.Release(sign);
                    sign = null;
                }
            }

            public void InteractableComplete(int interactableId)
            {
                
            }

            public void OnUpdateProgress()
            {
                var content = GetProgressContent(BattleConfigManager.GetLangText(config.rpg_mission_task_des));
                if (config.is_hide == 0)
                {
                    MissionManager.Instance.UpdateTaskProgressUI(content,index,hasFinish);
                }
               
                if (showUIEvent)
                {
                    content = GetProgressContent(null);
                    var type = 0;
                    if (taskType == EBattleTaskType.KillUnit)
                    {
                        type = (int)GetParam(2);
                    }
                    if (type == 1)
                    {
                        if (bossUnit == null)
                        {
                            var unitId = GetParam(0);
                            bossUnit = UnitManager.Instance.GetUnitByHeroId((int)unitId);
                        }

                        if (bossUnit != null)
                        {
                            content = BattleConfigManager.GetLangText(bossUnit.Name);
                        }
                        else
                        {
                            return;
                        }
                    }
                    StageManager.Instance.UpdateProgressUI(content,GetMissionProgressValue(),type);
                }
            }
            
            public float GetMissionProgressValue()
            {
                if (taskType == EBattleTaskType.KillUnit)
                {
                    var unitId = GetParam(0);
                    var count = GetParam(1);
                    var type = GetParam(2);
                    if (type == 1)
                    {
                        if (bossUnit == null)
                        {
                            return 0;
                        }
                        return (float)bossUnit.currentHp / bossUnit.totalHp;
                    }
                    return counter / count;
                }
                else if (taskType == EBattleTaskType.HoldOnByTime)
                {
                    return (TimeManager.time - startTime) / GetParam(0);
                }
                else if (taskType == EBattleTaskType.GetDollar)
                {
                    return (float)SurvivorDataManager.Instance.dollar / GetParam(0);
                }
                else if (taskType == EBattleTaskType.UnitReachRegion)
                {
                    return 0;
                }
                else if (taskType == EBattleTaskType.UnitRescue)
                {
                    if (targetUnit == null)
                    {
                        targetUnit = UnitManager.Instance.GetUnitByHeroId((int)GetParam(0));
                        if (targetUnit != null)
                        {
                            targetUnit.onHpChange = OnUpdateProgress;
                        }
                    }
                    if (targetUnit != null)
                    {
                        return (float)targetUnit.currentHp / targetUnit.totalHp;
                    }
                }
                return 0;
            }

            public string GetProgressContent(string format)
            {
                if (taskType == EBattleTaskType.KillUnit)
                {
                    var unitId = GetParam(0);
                    var count = GetParam(1);
                    string content;
                    if (format == null)
                    {
                        format = "{0}/{1}";
                    }
                    return string.Format(format, counter,count);
                }
                else if (taskType == EBattleTaskType.InteractiveRegion)
                {
                    var region = interactableRegion;
                    var regionTime = interactable.totalDuration;
                    string content;
                    if (format == null)
                    {
                        format = "{0}";
                    }
                    if (startTime > 0)
                    {
                        content = string.Format(format, (regionTime - (TimeManager.time - startTime)).ToString("#0.0") + "s");
                    }
                    else
                    {
                        var distance = Vector3.Distance(region.position,StageManager.Instance.TeamGroup.Position);
                        content = string.Format(format, distance.ToString("#0.0") + "m");
                    }
                    return content;
                }
                else if (taskType == EBattleTaskType.TeamReachRegion)
                {
                    if (format == null)
                    {
                        format = "{0}";
                    }
                    var region = interactableRegion;
                    var distance = Vector3.Distance(region.position,StageManager.Instance.TeamGroup.Position);
                    return string.Format(format, distance.ToString("#0.0") + "m");
                }
                else if (taskType == EBattleTaskType.HoldOnByTime)
                {
                    if (format == null)
                    {
                        format = "{0}";
                    }
                    var time = GetParam(0);
                    var content = string.Format(format,  (time - (TimeManager.time - startTime)).ToString("#0.0") + "s");
                    return content;
                }
                else if (taskType == EBattleTaskType.GetDollar)
                {
                    if (format == null)
                    {
                        format = "{0}/{1}";
                    }
                    var count = GetParam(0);
                    return string.Format(format,SurvivorDataManager.Instance.dollar,count);
                }
                else if (taskType == EBattleTaskType.UnitReachRegion)
                {
                    if (format == null)
                    {
                        format = "{0}";
                    }

                    var selfPosition = StageManager.Instance.TeamGroup.Position;
                    if (targetUnit != null)
                    {
                        selfPosition = targetUnit.position;
                    }
                    var distance = Vector3.Distance(interactableRegion.position,selfPosition);
                    var content = string.Format(format, distance.ToString("#0.0") + "m");
                    return content;
                }

                return string.Empty;
            }

            public void OnComplete()
            {
                if (showUIEvent)
                {
                    StageManager.Instance.HideProgressUI();
                    showUIEvent = false;
                }

                if (config.next_mission > 0)
                {
                    Instance.SetNextTask(this,config.next_mission);
                }
                MissionManager.Instance.OnOneTaskComplete();
            }
        }
        
        private List<MissionTask> taskList = new List<MissionTask>();
        private bool isPause;

        private int allTaskCount;
        private int finishTaskCount;
		public void Initialize()
        {
            
        }

        public string GetMissionContent(int missionId,string format)
        {
            for (int i = 0; i < taskList.Count; i++)
            {
                var task = taskList[i];
                if (task.config.id == missionId)
                {
                    return task.GetProgressContent(format);
                }
            }
            return string.Empty;
        }

        public float GetMissionProgressValue(int missionId)
        {
            for (int i = 0; i < taskList.Count; i++)
            {
                var task = taskList[i];
                if (task.config.id == missionId)
                {
                    return task.GetMissionProgressValue();
                }
            }
            return 0;
        }

        public void BindMissionToUI(int missionId)
        {
            for (int i = 0; i < taskList.Count; i++)
            {
                var task = taskList[i];
                if (task.config.id == missionId)
                {
                    task.showUIEvent = true;
                    task.OnUpdateProgress();
                    break;
                }
            }
        }
        
        public void SetTasks(List<int> ids)
        {
            taskList.Clear();
            finishTaskCount = 0;
            allTaskCount = 0;
            foreach (var id in ids)
            {
                var task = CreateTask(id,allTaskCount);
                taskList.Add(task);
            }
        }

        private MissionTask CreateTask(int id,int index)
        {
            var task = new MissionTask();
            var config = BattleConfigManager.Instance.GetTaskConfig(id);
            task.param = config.value;
            task.taskType = (EBattleTaskType)config.type;
            task.counter = 0;
            task.config = config;
            task.hasFinish = false;
            task.index = index;
            task.TaskStageType = config.stage_condition_type;
            task.Init();
            if (task.TaskStageType == 0)
            {
                allTaskCount++;
            }
            return task;
        }

        private void ResetTaskData()
        {
            
        }
        
        public void Update()
        {
            if (!SurvivorManager.isMissionActive)
            {
                return;
            }
            for (int i = 0; i < taskList.Count; i++)
            {
                var task = taskList[i];
                if (!task.hasFinish)
                {
                    if (task.taskType == EBattleTaskType.InteractiveRegion)
                    {
                        if (task.OnCheckInteractable())
                        {
                            task.OnComplete();
                        }
                    }
                    else if (task.taskType == EBattleTaskType.TeamReachRegion)
                    {
                        if (task.OnCheckRegion())
                        {
                            task.OnComplete();
                        }
                    }
                    else if (task.taskType == EBattleTaskType.HoldOnByTime)
                    {
                        if (task.OnCheckTimer())
                        {
                            task.OnComplete();
                        }
                    }
                    else if (task.taskType == EBattleTaskType.UnitReachRegion)
                    {
                        if (task.OnUnitReachRegion())
                        {
                            task.OnComplete();
                        }
                    }
                }
            }
        }

        private void SetNextTask(MissionTask task, int nextId)
        {
            taskList.Insert(task.index, CreateTask(nextId, task.index));
        }

        public void OnOneTaskComplete()
        {
            finishTaskCount++;
            CheckAllFinish();
        }


        public void OnGetDollar()
        {
            if (!SurvivorManager.isMissionActive)
            {
                return;
            }

            if (isPause)
            {
                return;
            }
            for (int i = 0; i < taskList.Count; i++)
            {
                var task = taskList[i];
                if (task.OnGetDollar())
                {
                    task.OnComplete();
                }
            }
        }
        
        
        public void OnKill(int team,int heroId)
        {
            if (!SurvivorManager.isMissionActive)
            {
                return;
            }
            if (isPause)
            {
                return;
            }
            for (int i = 0; i < taskList.Count; i++)
            {
                var task = taskList[i];
                if (task.OnKill(team, heroId))
                {
                    finishTaskCount++;
                }
            }

            CheckAllFinish();
        }

        private void CheckAllFinish()
        {
            if (finishTaskCount >= allTaskCount)
            {
                MissionComplete();
            }
        }

        public void Pause()
        {
            isPause = true;
        }

        public void Resume()
        {
            isPause = false;
        }
        
        public void MissionComplete()
        {
            if (isPause)
            {
                return;
            }
            StageManager.Instance.StageToNext();
        }

        public void UpdateTaskProgressUI(string content,int index,bool isFinish)
        {
            ResidentHandler.Inst.GetFunction("L_SurvivorManager.UpdateTaskProgress").Action(content,index,isFinish);
        }

        public void OnTimelineComplete()
        {
            for (int i = 0; i < taskList.Count; i++)
            {
                var task = taskList[i];
                if (task.taskType == EBattleTaskType.Timeline)
                {
                    task.OnComplete();
                }
            }
        }
        
        public override void Dispose()
        {
            isPause = false;
            taskList.Clear();
            allTaskCount = 0;
            finishTaskCount = 0;
        }
    }
}
